package com.jgzx.redis.service;

import com.jgzx.redis.config.RedisEnum;
import com.jgzx.utils.BeanToMapUtil;
import com.jgzx.utils.SerializeUtil;
import com.jgzx.utils.SpringContextUtil;
import org.springframework.stereotype.Service;
import redis.clients.jedis.*;
import redis.clients.jedis.params.GeoRadiusParam;

import java.util.*;

/**
 * @author jackesy
 * @className: RedisService
 * @description: redis操作service
 * @create 2021/1/16 下午4:15
 **/
@Service
public class RedisService {

    /**
     * 获取Jedis连接
     * @param redisEnum 数据库编号枚举
     * @return
     */

    private Jedis getJedis(RedisEnum redisEnum){
        JedisPool jedisPool = SpringContextUtil.getBean("jedisPool" + redisEnum.ordinal(), JedisPool.class);
        Jedis jedis = jedisPool.getResource();
        return jedis;
    }

    /*******************************************************位图********************************************************/
    /**
     * 对key所存储的字符串值,设置或清除指定偏移量上的位(bit).
     * 位的设置或者清除取决于value参数,可以是0也可以是1.
     * @param redisEnum
     * @param key
     * @param offset
     * @return 返回指定偏移量原来储存的位
     */
    public Boolean setBit(RedisEnum redisEnum, String key, long offset){
        Jedis jedis = this.getJedis(redisEnum);
        Boolean setbit = jedis.setbit(key, offset, true);
        jedis.close();
        return setbit;
    }

    /**
     * 对key所存储的字符串值,获取指定偏移量上的位(bit)
     * 当offset比字符串值的长度大,或者key不存在时,返回0
     * @param redisEnum
     * @param key
     * @param offset
     * @return
     */
    public Boolean getBit(RedisEnum redisEnum, String key, long offset){
        Jedis jedis = this.getJedis(redisEnum);
        Boolean getbit = jedis.getbit(key, offset);
        jedis.close();
        return getbit;
    }

    /**
     * 统计指定位区间上值为1的个数
     * @param redisEnum
     * @param key
     * @return
     */
    public Long bitcount(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long bitcount = jedis.bitcount(key);
        jedis.close();
        return bitcount;
    }

    /**
     * 返回位图中第一个值为bit的二进制位的位置
     * 在默认情况下,命令将检测到的整个位图,但用户也可以通过可选的start参数和end参数指定要检测的范围
     * @param redisEnum
     * @param key
     * @return
     */
    public Long bitpos(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long bitpos = jedis.bitpos(key, true);
        jedis.close();
        return bitpos;
    }

    /**
     * 对一个或多个保存二进制位的字符串key进行位元操作，并将结果保存到destkey上。
     * @param redisEnum
     * @param destkey
     * @param bitOP
     * @param keys
     * @return
     */
    public Long bitop(RedisEnum redisEnum, String destkey, BitOP bitOP, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Long bitpos = jedis.bitop(bitOP, destkey , keys);
        jedis.close();
        return bitpos;
    }

    /**
     * 通过bitfield命令可以一次性操作多个比特位域，它会执行一系列操作并返回一个响应数组，这个数组中的元素对应参数列表中的相应操作的执行结果
     * @param redisEnum
     * @param key
     * @return
     */
    public List<Long> bitfield(RedisEnum redisEnum, String key, String type){
        Jedis jedis = this.getJedis(redisEnum);
        List<Long> get = jedis.bitfield(key, "GET", type, "0");
        jedis.close();
        return get;
    }

    /*******************************************************事务********************************************************/

    /**
     * 监视key,如果在事务执行之前这些key被其他命令所改动，那么事务将被打断
     * 返回值OK
     * @param redisEnum
     * @param key
     * @return
     */
    public String watch(RedisEnum redisEnum, String... key){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.watch(key);
        return s;
    }

    /**
     * 取消WATCH命令对所有key的监视
     * 返回值OK
     * @param redisEnum
     * @param key
     * @return
     */
    public String unWatch(RedisEnum redisEnum, String... key){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.watch(key);
        return s;
    }

    /**
     * 获取事务对象,调用此方法即可开启事务，事务提交：Transaction.exec();事务取消：Transaction.discard()
     * 事务块内的多条命令会按照先后顺序被放进一个队列当中，最后由EXEC命令原子性(atomic)地执行
     * 返回值为事务对象Transaction
     * @param redisEnum
     * @return
     */
    public Transaction multi(RedisEnum redisEnum){
        Jedis jedis = this.getJedis(redisEnum);
        Transaction t = jedis.multi();
        return t;
    }

    /****************************************************GEO地理位置****************************************************/

    /**
     * 添加单个经纬度地理位置
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param longitude 经度
     * @param latitude 维度
     * @param member 成员
     * @return
     */
    public Long geoadd(RedisEnum redisEnum, String key, double longitude, double latitude, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.geoadd(key, longitude, latitude, member);
        return i;
    }

    /**
     * 批量添加纬度地理位置
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param memberCoordinateMap geo地理位置坐标
     * @return
     */
    public Long geoadd(RedisEnum redisEnum, String key, Map<String, GeoCoordinate> memberCoordinateMap){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.geoadd(key, memberCoordinateMap);
        return i;
    }

    /**
     * 返回两个给定位置之间的距离
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member1 成员1
     * @param member2 成员2
     * @param unit 距离单位
     * @return
     */
    public Double geodist(RedisEnum redisEnum, String key, String member1, String member2, GeoUnit unit){
        Jedis jedis = this.getJedis(redisEnum);
        Double d = jedis.geodist(key, member1, member2, unit);
        return d;
    }

    /**
     * 返回所有给定位置元素的位置
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param members 成员数组
     * @return
     */
    public List<GeoCoordinate> geopos(RedisEnum redisEnum, String key, String... members){
        Jedis jedis = this.getJedis(redisEnum);
        List<GeoCoordinate> list = jedis.geopos(key, members);
        return list;
    }

    /**
     * 以给定的经纬度为中心， 返回键包含的位置元素当中， 与中心的距离不超过给定最大距离的所有位置元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param longitude 经度
     * @param latitude 纬度
     * @param radius 半径距离
     * @param unit 距离单位
     * @return
     */
    public List<GeoRadiusResponse> georadius(RedisEnum redisEnum, String key, double longitude, double latitude, double radius, GeoUnit unit){
        Jedis jedis = this.getJedis(redisEnum);
        GeoRadiusParam param = GeoRadiusParam.geoRadiusParam();
        param.withDist().withCoord().sortAscending();
        List<GeoRadiusResponse> list = jedis.georadius(key, longitude, latitude, radius, unit, param);
        return list;
    }

    /**
     * 以给定的成员为中心，返回键包含的位置元素当中，与中心的距离不超过给定最大距离的所有位置元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @param radius 半径距离
     * @param unit 距离单位
     * @return
     */
    public List<GeoRadiusResponse> georadiusByMember(RedisEnum redisEnum, String key, String member, double radius, GeoUnit unit){
        Jedis jedis = this.getJedis(redisEnum);
        GeoRadiusParam param = GeoRadiusParam.geoRadiusParam();
        param.withDist().withCoord().sortAscending();
        List<GeoRadiusResponse> list = jedis.georadiusByMember(key, member, radius, unit, param);
        return list;
    }

    /*****************************************************字符串********************************************************/
    /**
     * 设置指定key的值，过期时间单位为秒
     * 设置成功返回OK
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @param exT 过期时间，小于等于0为永不过期
     * @return
     */
    public String set(RedisEnum redisEnum, String key, String value, int exT) {
        Jedis jedis = this.getJedis(redisEnum);
        String s = null;
        if (exT >0) {
            s = jedis.setex(key, exT, value);
        } else {
            s = jedis.set(key, value);
        }
        jedis.close();
        return s;
    }

    /**
     * 设置对象list到redis
     * 设置成功返回OK
     * @param redisEnum
     * @param key
     * @param list
     * @return
     */
    public <T> String setList(RedisEnum redisEnum, String key , List<T> list){
        Jedis jedis = this.getJedis(redisEnum);
        byte[] bytes = SerializeUtil.toBytes(list);
        String s = jedis.set(key.getBytes(), bytes);
        jedis.close();
        return s;
    }

    /**
     * 获取对象list
     * @param redisEnum
     * @param key
     * @return
     */
    public <T> List<T> getList(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        byte[] in = jedis.get(key.getBytes());
        if(in ==null || in.length <=0){
            return null;
        }
        List<T> list = (List<T>) SerializeUtil.toObject(in);
        jedis.close();
        return list;
    }

    /**
     * key不存在时才能设置成功，防止覆盖原来的值
     * 设置成功返回1，失败返回0
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @return
     */
    public Long setnx(RedisEnum redisEnum, String key, String value){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.setnx(key, value);
        jedis.close();
        return i;
    }

    /**
     * 获取指定key的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public String get(RedisEnum redisEnum, String key) {
        Jedis jedis = this.getJedis(redisEnum);
        String val = jedis.get(key);
        jedis.close();
        return val;
    }

    /**
     * 获取所有(一个或多个)给定key的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public List<String> mget(RedisEnum redisEnum, String... key) {
        Jedis jedis = this.getJedis(redisEnum);
        List<String> l = jedis.mget(key);
        jedis.close();
        return l;
    }

    /**
     * 设置指定key的值，并返回key的旧值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @return 旧值
     */
    public String getSet(RedisEnum redisEnum, String key, String value) {
        Jedis jedis = this.getJedis(redisEnum);
        String val = jedis.getSet(key, value);
        jedis.close();
        return val;
    }

    /**
     * 为指定的key的值追加值
     * 返回追加指定值之后，key的值得长度
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @return 旧值
     */
    public Long append(RedisEnum redisEnum, String key, String value) {
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.append(key, value);
        jedis.close();
        return i;
    }

    /**
     * 设置key的过期时间
     * 设置成功返回1，失败返回0
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param exT 过期时间
     * @return
     */
    public Long expire(RedisEnum redisEnum, String key, int exT){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.expire(key, exT);
        jedis.close();
        return i;
    }

    /**
     * 移除key的过期时间，使得key永不过期
     * 移除成功返回1，如果key不存在或key没有设置过期时间返回0
     * @param redisEnum 数据库编号枚举
     * @param  key 键
     * @return
     */
    public Long persist(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.persist(key);
        jedis.close();
        return i;
    }

    /**
     * 返回key的剩余生存时间，以秒为单位
     * 当key不存在时，返回-2；当key存在但没有设置剩余生存时间时，返回-1
     * @param redisEnum 数据库编号枚举
     * @param  key 键
     * @return
     */
    public Long ttl(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.ttl(key);
        jedis.close();
        return i;
    }

    /**
     * 返回key的剩余生存时间，以毫秒为单位
     * 当key不存在时，返回-2；当key存在但没有设置剩余生存时间时，返回-1
     * @param redisEnum 数据库编号枚举
     * @param  key 键
     * @return
     */
    public Long pttl(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.pttl(key);
        jedis.close();
        return i;
    }

    /**
     * 批量删除已存在的键,不存在的key会被忽略
     * 返回被删除key的数量
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Long del(RedisEnum redisEnum, String... key) {
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.del(key);
        jedis.close();
        return i;
    }

    /**
     * 根据key模糊删除
     * 返回被删除key的数量
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public void delBatch(RedisEnum redisEnum, String key) {
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> keys= jedis.keys(key+ "*");
        if (keys != null && keys.size()>0){
            String[] keyArr = keys.toArray(new String[keys.size()]);
            this.del(redisEnum, keyArr);
        }
        jedis.close();
    }
    /**
     * 查找所有符合指定key的key集合
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Set<String> keys(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> set = jedis.keys(key + "*");
        jedis.close();
        return set;
    }

    /**
     * 判断指定key是否存在
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Boolean exists(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Boolean b = jedis.exists(key);
        jedis.close();
        return b;
    }

    /**
     * 将key所储存的值加上给定的增量值
     * 返回加上指定的增量值之后的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param increment 增量
     * @return
     */
    public Long incrBy(RedisEnum redisEnum, String key, long increment) {
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.incrBy(key, increment);
        jedis.close();
        return i;
    }

    /**
     * 将key所储存的值减去给定的增量值
     * 返回减去指定减量值之后的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param increment 增量
     * @return
     */
    public Long decrBy(RedisEnum redisEnum, String key, long increment) {
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.decrBy(key, increment);
        jedis.close();
        return i;
    }

    /*****************************************************哈希(键值对象)*************************************************/
    /**
     * 向哈希表中存储对象，field-value (域-值)对的形式
     * 设置成功，返回OK
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param obj 对象
     * @return
     */
    public String hmset(RedisEnum redisEnum, String key, Object obj){
        Map<String, String> map = BeanToMapUtil.beanToMap(obj);
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.hmset(key, map);
        jedis.close();
        return s;
    }



    /**
     * 向哈希表中存储对象，field-value (域-值)对的形式
     * 设置成功，返回OK
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param obj 对象
     * @return
     */
    public String hmsetMap(RedisEnum redisEnum, String key, Map<String, String> obj){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.hmset(key, obj);
        jedis.close();
        return s;
    }

    /**
     * 将哈希表key中的字段field的值设为value
     * 新建字段返回1，旧字段返回0
     * @param redisEnum 数据库编号枚举
     * @param  key 键
     * @param field 字段
     * @param value 值
     * @return
     */
    public Long hset(RedisEnum redisEnum, String key, String field, String value){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.hset(key, field, value);
        jedis.close();
        return i;
    }

    /**
     * 获取存储在哈希表中指定字段的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param field 字段
     * @return
     */
    public String hget(RedisEnum redisEnum, String key, String field){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.hget(key, field);
        jedis.close();
        return s;
    }

    /**
     * 获取哈希表中所有的字段
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Set<String> hkeys(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.hkeys(key);
        jedis.close();
        return s;
    }

    /**
     * 获取哈希表中所有值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public List<String> hvals(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        List<String> l = jedis.hvals(key);
        jedis.close();
        return l;
    }

    /**
     * 获取哈希表所有字段和值,即获取Map
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Map<String,String> hgetAll(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Map<String,String> m = jedis.hgetAll(key);
        jedis.close();
        return m;
    }

    /**
     * 获取哈希表所有字段和值,即获取对象
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param beanClass bean对象class
     * @return
     */
    public <T> T hgetAll(RedisEnum redisEnum, String key, Class<T> beanClass){
        Map<String,String> map = hgetAll(redisEnum, key);
        return BeanToMapUtil.mapToBean(map, beanClass);
    }

    /**
     * 为哈希表中的指定字段的整数值加上增量increment
     * 执行成功，返回字段的新值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param field 字段
     * @param increment 增量
     * @return
     */
    public Long hincrBy(RedisEnum redisEnum, String key, String field, long increment){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.hincrBy(key, field, increment);
        jedis.close();
        return i;
    }

    /**
     * 为哈希表中的指定字段的浮点数值加上增量increment
     * 执行成功，返回字段的新值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param field 字段
     * @param increment 增量
     * @return
     */
    public Double hincrByFloat(RedisEnum redisEnum, String key, String field, double increment){
        Jedis jedis = this.getJedis(redisEnum);
        Double i = jedis.hincrByFloat(key, field, increment);
        jedis.close();
        return i;
    }

    /*****************************************************list列表******************************************************/
    /**
     * 将一个或多个值插入到list列表头部，从左边插入
     * 执行成功，返回列表的长度
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @return
     */
    public Long lpush(RedisEnum redisEnum, String key, String... value){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.lpush(key, value);
        jedis.close();
        return i;
    }

    /**
     * 将一个或多个值插入到list列表尾部，从右边插入
     * 执行成功，返回列表的长度
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param value 值
     * @return
     */
    public Long rpush(RedisEnum redisEnum, String key, String... value){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.rpush(key, value);
        jedis.close();
        return i;
    }

    /**
     * 获取list获取列表的长度
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Long llen(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.llen(key);
        jedis.close();
        return i;
    }

    /**
     * 获取list列表指定范围内的元素
     * [0,-1]范围，是获取列表所有元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引
     * @return
     */
    public List<String> lrange(RedisEnum redisEnum, String key, long start, long end){
        Jedis jedis = this.getJedis(redisEnum);
        List<String> l = jedis.lrange(key, start, end);
        jedis.close();
        return l;
    }

    /**
     * 通过索引设置list列表元素的值
     * 设置成功，返回OK
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public String lset(RedisEnum redisEnum, String key, long index, String value){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.lset(key, index, value);
        jedis.close();
        return s;
    }

    /**
     * 通过索引获取list列表元素的值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param index 索引
     * @return
     */
    public String lindex(RedisEnum redisEnum, String key, long index){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.lindex(key, index);
        jedis.close();
        return s;
    }

    /**
     * 移除并返回列表的第一个元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public String lpop(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.lpop(key);
        jedis.close();
        return s;
    }

    /**
     * 移除并返回列表的最后一个元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public String rpop(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.rpop(key);
        jedis.close();
        return s;
    }

    /**
     * 对列表进行修剪，只保留指定区间内的元素，不在指定区间之内的元素都将被删除
     * 操作成功，返回OK
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引
     * @return
     */
    public String ltrim(RedisEnum redisEnum, String key, long start, long end){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.ltrim(key, start, end);
        jedis.close();
        return s;
    }

    /*****************************************************set集合*******************************************************/
    /**
     * 向set集合添加一个或多个成员
     * 设置成功返回1，设置失败或者值已存在返回0
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Long sadd(RedisEnum redisEnum, String key, String... member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.sadd(key, member);
        jedis.close();
        return i;
    }

    /**
     * 判断成员元素是否是set集合的成员
     * 如果成员元素是集合的成员,返回1;如果成员元素不是集合的成员,或key不存在,返回0
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Boolean sismember(RedisEnum redisEnum, String key, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Boolean b = jedis.sismember(key, member);
        jedis.close();
        return b;
    }

    /**
     * 移除set集合中一个随机元素，移除后会返回移除的元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public String spop(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        String s = jedis.spop(key);
        jedis.close();
        return s;
    }

    /**
     * 移除set集合中一个或多个随机元素，移除后会返回移除的元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param count 数量
     * @return
     */
    public Set<String> spop(RedisEnum redisEnum, String key, long count){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.spop(key, count);
        jedis.close();
        return s;
    }

    /**
     * 返回集合中的一个或多个随机元素,不对集合进行任何改动
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param count 数量
     * @return
     */
    public List<String> srandmember(RedisEnum redisEnum, String key, int count){
        Jedis jedis = this.getJedis(redisEnum);
        List<String> l = jedis.srandmember(key, count);
        jedis.close();
        return l;
    }

    /**
     * 移除set集合中的一个或多个成员元素
     * 返回被成功移除的元素的数量，不包括被忽略的元素
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param members 成员数组
     * @return
     */
    public Long srem(RedisEnum redisEnum, String key, String... members){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.srem(key, members);
        jedis.close();
        return i;
    }

    /**
     * 返回set集合中的所有的成员
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Set<String> smembers(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.smembers(key);
        jedis.close();
        return s;
    }

    /**
     * 返回set集合的成员数
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Long scard(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.scard(key);
        jedis.close();
        return i;
    }

    /**
     * 返回给定所有集合的差集
     * @param redisEnum 数据库编号枚举
     * @param keys 键数组
     * @return
     */
    public Set<String> sdiff(RedisEnum redisEnum, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.sdiff(keys);
        jedis.close();
        return s;
    }

    /**
     * 将所有集合的差集并存储在dstkey中
     * 返回存储差集的集合的元素数量
     * @param redisEnum 数据库编号枚举
     * @param dstkey 存储的集合key
     * @param keys 键数组
     * @return
     */
    public Long sdiffstore(RedisEnum redisEnum, String dstkey, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.sdiffstore(dstkey, keys);
        jedis.close();
        return i;
    }

    /**
     * 返回给定所有集合的交集
     * @param redisEnum 数据库编号枚举
     * @param keys 键数组
     * @return
     */
    public Set<String> sinter(RedisEnum redisEnum, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.sinter(keys);
        jedis.close();
        return s;
    }

    /**
     * 将所有集合的交集并存储在dstkey中
     * 返回存储交集的集合的元素数量
     * @param redisEnum 数据库编号枚举
     * @param dstkey 存储的集合key
     * @param keys 键数组
     * @return
     */
    public Long sinterstore(RedisEnum redisEnum, String dstkey, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.sinterstore(dstkey, keys);
        jedis.close();
        return i;
    }

    /**
     * 返回给定所有集合的并集
     * @param redisEnum 数据库编号枚举
     * @param keys 键数组
     * @return
     */
    public Set<String> sunion(RedisEnum redisEnum, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.sunion(keys);
        jedis.close();
        return s;
    }

    /**
     * 将所有集合的并集并存储在dstkey中
     * 返回存储并集的集合的元素数量
     * @param redisEnum 数据库编号枚举
     * @param dstkey 存储的集合key
     * @param keys 键数组
     * @return
     */
    public Long sunionstore(RedisEnum redisEnum, String dstkey, String... keys){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.sunionstore(dstkey, keys);
        jedis.close();
        return i;
    }

    /**
     * 将指定成员member元素从srckey集合移动到dstkey集合
     * 操作成功返回1，如果member在srckey集合不存在或者操作失败返回0
     * @param redisEnum 数据库编号枚举
     * @param srckey 源集合key
     * @param dstkey 目标集合key
     * @param member
     * @return
     */
    public Long smove(RedisEnum redisEnum, String srckey, String dstkey, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.smove(srckey, dstkey, member);
        jedis.close();
        return i;
    }

    /*****************************************************有序集合******************************************************/
    /**
     * 向有序集合添加一个成员，或者更新已存在成员的分数
     * 设置成功,返回被成功添加的新成员的数量，不包括那些被更新的、已经存在的成员
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Long zadd(RedisEnum redisEnum, String key, double score, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zadd(key, score, member);
        jedis.close();
        return i;
    }

    /**
     * 向有序集合添加多个成员，或者更新已存在成员的分数
     * 设置成功,返回被成功添加的新成员的数量，不包括那些被更新的、已经存在的成员
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param scoreMembers 成员
     * @return
     */
    public Long zadd(RedisEnum redisEnum, String key, Map<String, Double> scoreMembers){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zadd(key, scoreMembers);
        jedis.close();
        return i;
    }

    /**
     * 获取有序集合的成员数
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @return
     */
    public Long zcard(RedisEnum redisEnum, String key){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zcard(key);
        jedis.close();
        return i;
    }

    /**
     * 返回有序集合中指定区间分数的成员数
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param max 最大分数
     * @param min 最小分数
     * @return
     */
    public Long zcount(RedisEnum redisEnum, String key, double max, double min){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zcount(key, max, min);
        jedis.close();
        return i;
    }

    /**
     * 移除有序集中的一个或多个成员，不存在的成员将被忽略
     * 返回被成功移除的成员的数量，不包括被忽略的成员
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Long zrem(RedisEnum redisEnum, String key, String... member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zrem(key, member);
        jedis.close();
        return i;
    }

    /**
     * 有序集合中对指定成员的分数加上增量increment
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param score 分数
     * @param member 成员
     * @return
     */
    public Double zincrby(RedisEnum redisEnum, String key, double score, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Double d = jedis.zincrby(key, score, member);
        jedis.close();
        return d;
    }

    /**
     * 返回有序集中指定成员的分数值
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Double zscore(RedisEnum redisEnum, String key, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Double d = jedis.zscore(key, member);
        jedis.close();
        return d;
    }

    /**
     * 返回有序集中指定成员的排名
     * 有序集成员按分数值递增(从小到大)排序,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Long zrank(RedisEnum redisEnum, String key, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zrank(key, member);
        jedis.close();
        return i;
    }

    /**
     * 返回有序集中指定分数区间内的所有的成员，不带分数值
     * 有序集成员按分数值递增(从小到大)的次序排列,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param max 最大分数
     * @param min 最小分数
     * @return
     */
    public Set<String> zrangeByScore(RedisEnum redisEnum, String key, double max, double min){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.zrangeByScore(key, max, min);
        jedis.close();
        return s;
    }

    /**
     * 返回有序集中指定分数区间内的所有的成员，带分数值
     * 有序集成员按分数值递增(从小到大)的次序排列,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param max 最大分数
     * @param min 最小分数
     * @return
     */
    public Set<Tuple> zrangeByScoreWithScores(RedisEnum redisEnum, String key, double min, double max){
        Jedis jedis = this.getJedis(redisEnum);
        Set<Tuple> s = jedis.zrangeByScoreWithScores(key, min, max);
        jedis.close();
        return s;
    }

    /**
     * 返回有序集中指定成员的排名
     * 有序集成员按分数值递减(从大到小)排序,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param member 成员
     * @return
     */
    public Long zrevrank(RedisEnum redisEnum, String key, String member){
        Jedis jedis = this.getJedis(redisEnum);
        Long i = jedis.zrevrank(key, member);
        jedis.close();
        return i;
    }

    /**
     * 返回有序集中指定分数区间内的所有的成员，不带分数值
     * 有序集成员按分数值递减(从大到小)的次序排列,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param max 最大分数
     * @param min 最小分数
     * @return
     */
    public Set<String> zrevrangeByScore(RedisEnum redisEnum, String key, double max, double min){
        Jedis jedis = this.getJedis(redisEnum);
        Set<String> s = jedis.zrevrangeByScore(key, max, min);
        jedis.close();
        return s;
    }

    /**
     * 返回有序集中指定分数区间内的所有的成员，带分数值
     * 有序集成员按分数值递减(从大到小)的次序排列,具有相同分数值的成员按字典序的逆序排列
     * @param redisEnum 数据库编号枚举
     * @param key 键
     * @param max 最大分数
     * @param min 最小分数
     * @return
     */
    public Set<Tuple> zrevrangeByScoreWithScores(RedisEnum redisEnum, String key, double min, double max){
        Jedis jedis = this.getJedis(redisEnum);
        Set<Tuple> s = jedis.zrevrangeByScoreWithScores(key, min, max);
        jedis.close();
        return s;
    }
}
